﻿using Muccu.Contracts;
using System;
using System.Security.Principal;
using System.Text;
using System.Web;
using System.Web.Security;

namespace Muccu
{
    public abstract class JavaScriptService : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            Response mResponse = null;
            try
            {
                var rpc = Request.FromStream(context.Request.InputStream);
                try
                {
                    if (rpc != null)
                    {
                        FormsAuthenticationTicket fa_ticket;
                        if (rpc.Ticket != null && (fa_ticket = FormsAuthentication.Decrypt(rpc.Ticket)) != null)
                        {
                            if (fa_ticket.Expired)
                                mResponse = Response.E_32100;
                            else
                            {
                                context.User = new GenericPrincipal((IIdentity)new FormsIdentity(fa_ticket), new string[0]);
                            }
                        }
                        if (mResponse == null)
                        {
                            var dispatcher = this.DispatcherCache.Get(this.GetType());
                            mResponse = dispatcher.Execute(this, rpc);
                        }
                    }
                    else
                    {
                        mResponse = Response.E_32600;
                    }

                }
                catch (ArgumentException ex)
                {
                    mResponse = Response.CreateError(rpc.Id, -32602, ex.Message, ex.StackTrace);
                }
                catch (Exception ex)
                {
                    Exception inner = ex.InnerException ?? ex;
                    Tracer.WriteHandledException(inner);
                    mResponse = Response.CreateError(rpc.Id, -32100, inner.Message, inner.StackTrace);
                }
            }
            catch (Exception e)
            {
                mResponse = Response.E_32700;
                Tracer.WriteException(e);
            }

            context.Response.ContentEncoding = Encoding.UTF8;
            context.Response.ContentType = "application/json";
            Compressor.GZipIfSupportedByClient(context.Request, context.Response);

            if (mResponse != null)
            {
                if (mResponse.Error != null && context.IsCustomErrorEnabled)
                {
                    context.Response.Write(Response.E_CUSTOM_ERRORS_OFF.ToJson());
                }
                else
                {
                    context.Response.Write(mResponse.ToJson());
                }
                Tracer.WriteTrace("Result: {0}", mResponse.ToJson());
            }

            context.Response.End();
        }

        public bool IsReusable
        {
            get { return false; }
        }


        private static Cache<Type, Dispatcher> _staticDispatcher = new Cache<Type, Dispatcher>(type => new Dispatcher(type));
        private Cache<Type, Dispatcher> DispatcherCache
        {
            get { return _staticDispatcher; }
        }
    }
}
